package internal

import (
    "fmt"
    "io"
    "io/ioutil"
    "log"
    "net/http"
)

type Downloader struct {
    result  chan Part
    size    int
    workers int
}

func NewDownloader(result chan Part, size int, workers int) *Downloader {
    return &Downloader{result: result, size: size, workers: workers}
}

type Part struct {
    Data  []byte
    Index int
}

func (d *Downloader) Download(index int, url string) {
    client := &http.Client{}
    start := index * d.size
    dataRange := fmt.Sprintf("bytes=%d-%d", start, start+d.size-1)
    if index == d.workers-1 {
        dataRange = fmt.Sprintf("bytes=%d-", start)
    }

    log.Println(dataRange)

    request, err := http.NewRequest("GET", url, nil)
    if err != nil {
        // TODO:restart download
        return
    }

    request.Header.Add("Range", dataRange)
    resp, err := client.Do(request)
    if err != nil {
        // TODO:restart download
        return
    }
    defer resp.Body.Close()
    body, err := io.ReadAll(resp.Body)
    if err != nil {
        // TODO:restart download
        return
    }
    d.result <- Part{Data: body, Index: index}
}

func (d *Downloader) Merge(filename string) error {
    log.Println("start merge data")
    parts := make([][]byte, d.workers)
    counter := 0
    for part := range d.result {
        counter++
        parts[part.Index] = part.Data
        if counter == d.workers {
            break
        }
    }
    log.Println("sort data as original order")

    file := make([]byte, 0)
    for _, part := range parts {
        file = append(file, part...)
    }
    log.Println("write data into buffer array")
    return ioutil.WriteFile(filename, file, 0777)
}
